<script setup lang="ts">
import { ElButton, ElIcon, ElMessage } from 'element-plus';
import TaskEditDialog from '@/components/TaskEditDialog.vue';
import TaskList from './TaskList.vue';
import { RoutePointInfo, useTaskStore, useTimeRangeStore,useUserStore } from '@/store';
import { GeoJSONFeature, MapMouseEvent, Marker } from 'mapbox-gl';
import { toLonLatString } from 'common/src/utils/lnglat';
import { getCustomLocalTimeFormat } from 'common/src/utils/time';
import { getRollPitch, getSogCog, RouteAttitude, TaskItem,impTaskPack } from '@/services/task';
import { CloseBold } from '@element-plus/icons-vue';

const taskEditDialogRef = ref<InstanceType<typeof TaskEditDialog> | null>(null);
const taskListDialogRef = ref<InstanceType<typeof TaskList> | null>(null);
const taskEditVisible = ref(false);
const taskListVisible = ref(false);
const taskStore = useTaskStore();
const timeRangeStore = useTimeRangeStore();
const userStore = useUserStore();
const routePopContent = ref<HTMLDivElement | null>(null);

// ==== 导入任务包（zip） ====
const importFileRef = ref<HTMLInputElement | null>(null);
const onClickImport = () => {
  importFileRef.value?.click();
};
const onImportFileChange = async (e: Event) => {
  const input = e.target as HTMLInputElement;
  const file = input.files && input.files[0];
  if (!file) return;

  // 格式校验：仅 zip
  const ext = file.name.split('.').pop()?.toLowerCase();
  if (ext !== 'zip') {
    ElMessage.error('仅支持 .zip 文件');
    input.value = '';
    return;
  }

  const fd = new FormData();
  fd.append('task', file);
  try {
    await impTaskPack(fd);
    ElMessage.success('导入成功');
    refreshTaskList()
  } catch (err: any) {
    ElMessage.error(err?.message || '导入失败');
  } finally {
    // 重置 input，便于下次选择同名文件也能触发 change
    input.value = '';
  }
};

/** 点查信息是否显示气象，没有气象信息就不显示气象 */
const showPointWeather = computed(() => {
  if (taskStore.routePointInfo.windText === '--' && taskStore.routePointInfo.wave === undefined) {
    return false;
  }
  return true;
});

const handleCreateTask = () => {
  taskEditDialogRef.value?.editTask();
};

const handleEditTask = (task: TaskItem) => {
  taskEditDialogRef.value?.editTask(task);
};

const toggleTaskList = () => {
  // taskListVisible.value = !taskListVisible.value;
  if (!taskListVisible.value) {
    taskStore.getList();
  }
  taskListDialogRef.value?.toggleShow();
};

const refreshTaskList = () => {
  taskStore.getList();
};

const handleRoutePointClick = (e: MapMouseEvent & {
  features?: GeoJSONFeature[] | undefined;
}) => {
  const properties = e.features![0].properties as any;
  const { lat, lon, ts, sog, cog, id, type, idx } = properties;
  const task = taskStore.list.find(item => item.id === id);
  let pose: RouteAttitude[] = [];
  const { poses, custom } = taskListDialogRef.value?.getActiveTaskAttitudeInfo() || {};
  if (type) {
    pose = poses?.[type] || [];
  } else if (idx) {
    pose = custom?.[idx].pose || [];
  }
  const pointInfo: Partial<RoutePointInfo> = {
    lat, lon, latLng: toLonLatString(lon, lat),
    time: getCustomLocalTimeFormat(ts * 1000, 'YYYY-MM-DD HH:mm'),
    sog, cog,
    roll: undefined, pitch: undefined, windAngle: undefined, windSpd: undefined, wave: undefined,
  };
  if (task && pose.length) {
    const {roll, pitch, windAngle, windSpd, wave} = getRollPitch(pose, ts * 1000);
    Object.assign(pointInfo, { roll, pitch, windAngle, windSpd, wave });
  }
  taskStore.updateRoutePointInfo(pointInfo);
  taskStore.updateRoutePointMarker(lon, lat);
};

const updateShipMarkerPopup = () => {
  const { taskId, type } = taskStore.routePointInfo;
  const marker = taskStore.markerMap[taskId].route[type].ship;
  const { lng, lat } = marker.getLngLat();
  const timestamp = timeRangeStore.currentTime;
  const task = taskStore.list.find(item => item.id === taskId);
  const { id, poses } = taskListDialogRef.value?.getActiveTaskAttitudeInfo() || {};
  const pointInfo: Partial<RoutePointInfo> = {
    lat, lon: lng, latLng: toLonLatString(lng, lat),
    time: getCustomLocalTimeFormat(timestamp, 'YYYY-MM-DD HH:mm'),
    sog: undefined, cog: undefined,
    roll: undefined, pitch: undefined, windAngle: undefined, windSpd: undefined, wave: undefined,
  };
  if (task && task.id === id && poses?.[type]?.length) {
    const {roll, pitch, windAngle, windSpd, wave} = getRollPitch(poses[type], timestamp);
    Object.assign(pointInfo, { roll, pitch, windAngle, windSpd, wave });
  }
  if (task && task.routes[type]?.length) {
    const {sog, cog} = getSogCog(task.routes[type], timestamp);
    Object.assign(pointInfo, { sog, cog });
  }
  taskStore.updateRoutePointInfo(pointInfo);
  taskStore.updateRoutePointMarker(lng, lat);
};

const handleShipMarkerClick = (taskId: number, type: number) => {
  taskStore.routePointInfo.taskId = taskId;
  taskStore.routePointInfo.type = type;
  updateShipMarkerPopup();
};

watch(() => timeRangeStore.currentTime, () => {
  const { taskId } = taskStore.routePointInfo;
  if (taskId > -1) {
    // 先等marker位置更新，这样可以免去位置计算
    setTimeout(() => {
      updateShipMarkerPopup();
    }, 0);
  }
});

watch(() => userStore.taskPhase, () => {
  taskListDialogRef.value.setTaskInfoShow(false);
  taskListVisible.value =false
  taskEditVisible.value = false
})

onMounted(() => {
  taskStore.routePointMarker = new (Marker as any)({
    className: 'marker-popup spot-weather-marker',
    element: routePopContent.value! as HTMLDivElement,
    anchor: 'bottom-left',
    offset: [-2, -1],
  });
  taskStore.shipMarkerClickFn = handleShipMarkerClick;
});

defineExpose({
  handleRoutePointClick,
});
</script>

<template>
  <div class="top-left" v-if="userStore.taskPhase !== 5">
    <ElButton class="custom-btn" @click="() => toggleTaskList()">任务列表</ElButton>
    <ElButton v-if="false" class="custom-btn" @click="() => handleCreateTask()">任务创建</ElButton>
    <div style="margin-left: 12px;">
      <ElButton class="custom-btn" @click="() => onClickImport()">导入</ElButton>
      <input
        ref="importFileRef"
        type="file"
        accept=".zip,application/zip,application/x-zip-compressed"
        style="display: none;"
        @change="onImportFileChange"
      />
    </div>
  </div>
  <TaskEditDialog
    ref="taskEditDialogRef"
    v-model:visible="taskEditVisible"
    @update="() => refreshTaskList()"
  />
  <TaskList ref="taskListDialogRef" v-model:visible="taskListVisible" @edit="handleEditTask" />
  <div v-show="taskStore.infoShow.routePoint && showPointWeather" class="spot-weather-top">
    <div>经纬度: {{ taskStore.routePointInfo.latLng }}</div>
    <div>时间: {{ taskStore.routePointInfo.time }}</div>
    <div>航向: {{ taskStore.routePointInfo.cog === undefined ? '--' : `${taskStore.routePointInfo.cog.toFixed(0)}°` }}</div>
  </div>
  <div v-show="taskStore.infoShow.regionWxMsg" class="spot-weather-top">
    <div>{{ taskStore.regionWxMsgInfo.info }}</div>
    <ElIcon
      class="spot-weather-top-close"
      @click="() => taskStore.infoShow.regionWxMsg = false"
    ><CloseBold /></ElIcon>
  </div>
  <div ref="routePopContent" class="spot-weather-content">
    <div class="spot-weather-flag">
      <div v-show="taskStore.routePointInfo.roll !== undefined || taskStore.routePointInfo.pitch !== undefined">
        横纵摇: {{ taskStore.routePointInfo.roll === undefined ? '--' : `${taskStore.routePointInfo.roll.toFixed(2)}°` }} / {{
          taskStore.routePointInfo.pitch === undefined ? '--' : `${taskStore.routePointInfo.pitch.toFixed(2)}°`
        }}
      </div>
      <template v-if="showPointWeather">
        <div>风: {{ taskStore.routePointInfo.windText }}</div>
        <div>浪: {{ (taskStore.routePointInfo.wave || (taskStore.routePointInfo.wave === 0)) ? `${taskStore.routePointInfo.wave.toFixed(2)}m` : '--' }}</div>
      </template>
      <template v-else>
        <div>经纬度: {{ taskStore.routePointInfo.latLng }}</div>
        <div>时间: {{ taskStore.routePointInfo.time }}</div>
        <div>航向: {{ taskStore.routePointInfo.cog === undefined ? '--' : `${taskStore.routePointInfo.cog.toFixed(0)}°` }}</div>
      </template>
      <ElIcon
        class="spot-weather-close"
        @click.stop="() => taskStore.removeRoutePointMarker()"
      ><CloseBold /></ElIcon>
    </div>
    <div class="spot-weather-dot" />
  </div>
</template>

<style lang="less" scoped>
.top-left {
  position: absolute;
  left: 20px;
  top: 20px;
  z-index: 10;
  display: flex;
  flex-flow: row nowrap;
  .custom-btn {
    --el-button-text-color: #eee;
    background: linear-gradient( 180deg, #192248 0%, rgba(0,120,255,0.51) 100%);
    box-shadow: 0px 2px 2px 0px rgba(65,176,255,0);
    border-radius: 5px;
    border: 2px solid;
    border-image: linear-gradient(360deg, rgba(40, 98, 199, 1), rgba(40, 98, 198, 0)) 2 2;
    padding: 10px 20px 6px;
  }
  .custom-btn + .custom-btn {
    margin-left: 16px;
  }
}
</style>
